﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 * Http请求接收类，简化.NET的HTTP发送和接收数据操作。
 * 
 * 最后修改：2011-10-19
 * ************************************************************/
namespace Mozlite
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.IO;
    using System.Collections.Specialized;
    using System.IO.Compression;

    /// <summary>
    /// HTTP请求管理类。
    /// </summary>
    public class HttpRequester
    { 
        /// <summary>
        /// 默认最大自动转向次数。
        /// </summary>
        protected static int defaultMaxAutoRedirects = 10;
        /// <summary>
        /// 默认延迟时间。
        /// </summary>
        protected static int defaultTimeout = 0xea60;
        /// <summary>
        /// 默认引用地址。
        /// </summary>
        protected static string referer = null;
        /// <summary>
        /// 用户代理信息。
        /// </summary>
        protected static string userAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E)";//string.Format("Mozlite ({0}; .NET CLR {1};)", Environment.OSVersion.ToString(), Environment.Version.ToString());
        /// <summary>
        /// 通过URL地址创建<see cref="T:System.Net.HttpWebRequest"/>实例对象。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebRequest"/>实例对象。</returns>
        public static HttpWebRequest CreateRequest(string url)
        {
            return CreateRequest(url, referer);
        }
        /// <summary>
        /// 获取文本流。
        /// </summary>
        /// <param name="response"><see cref="T:System.Net.HttpWebRequest"/>实例对象。</param>
        /// <param name="encoding">返回编码枚举。</param>
        /// <returns>返回文本流。</returns>
        public static Stream GetStream(HttpWebResponse response, out Encoding encoding)
        {
            Stream stream = response.GetResponseStream();
            string name = response.ContentEncoding.Trim();
            try
            {
                encoding = Encoding.GetEncoding(name);
            }
            catch
            {
                try
                {
                    encoding = Encoding.GetEncoding(response.CharacterSet);
                }
                catch
                {
                    encoding = Encoding.UTF8;
                }
            }
            if (string.IsNullOrEmpty(name))
                return stream;
            if (name.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1)
            {
                return new GZipStream(stream, CompressionMode.Decompress);
            }
            else if (name.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1)
            {
                return new DeflateStream(stream, CompressionMode.Decompress);
            }
            return stream;
        }
        /// <summary>
        /// 获取文本流。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用网址。</param>
        /// <param name="encoding">返回编码枚举。</param>
        /// <returns>返回文本流。</returns>
        public static Stream GetStream(string url, string referral, out Encoding encoding)
        {
            return GetStream(GetResponse(url, referral), out encoding);
        }
        /// <summary>
        /// 通过URL地址创建<see cref="T:System.Net.HttpWebRequest"/>实例对象。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebRequest"/>实例对象。</returns>
        public static HttpWebRequest CreateRequest(string url, string referral)
        {
            ICredentials defaultCredentials = null;
            WebRequest req;
            if (url.IndexOf('@') > 0)
            {
                string[] parts = url.Split(new char[] { '@' });
                if (parts.Length >= 2)
                {
                    string[] arr = parts[0].Split(new char[] { ':' });
                    if (arr.Length == 3)
                    {
                        string userName = arr[1].TrimStart(new char[] { '/' });
                        string password = arr[2];
                        defaultCredentials = new NetworkCredential(userName, password);
                        url = url.Replace(string.Format("{0}:{1}@", userName, password), "");
                    }
                }
            }
            else
            {
                defaultCredentials = CredentialCache.DefaultCredentials;
            }
            try
            {
                req = WebRequest.Create(url);
            }
            catch
            {
                req = null;
            }
            HttpWebRequest request = req as HttpWebRequest;
            if (null != request)
            {
                request.UserAgent = userAgent;
                request.Referer = referral;
                request.Timeout = defaultTimeout;
                request.MaximumAutomaticRedirections = defaultMaxAutoRedirects;
                request.Headers.Add("Accept-Encoding", "gzip");
                request.KeepAlive = false;
                if (defaultCredentials != null)
                {
                    request.Credentials = defaultCredentials;
                }
                if (HasWebProxy)
                {
                    request.Proxy = WebProxy;
                }
            }
            return request;
        }
        /// <summary>
        /// 通过URL地址创建<see cref="T:System.Net.HttpWebRequest"/>实例对象。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebRequest"/>实例对象。</returns>
        public static HttpWebRequest CreateSafeRequest(string url, string referral)
        {
            HttpWebRequest request = CreateRequest(url, referral);
            if (request != null)
            {
                request.Timeout = 15000;
                request.MaximumAutomaticRedirections = 1;
                request.MaximumResponseHeadersLength = 32;
            }
            return request;
        }
        /// <summary>
        /// 获取<see cref="T:System.Net.HttpWebResponse"/>实例中返回的字符串。
        /// </summary>
        /// <param name="response"><see cref="T:System.Net.HttpWebResponse"/>实例对象。</param>
        /// <returns>返回页面的字符串。</returns>
        public static string GetPageText(HttpWebResponse response)
        {
            return GetPageText(response, null);
        }
        /// <summary>
        /// 获取<see cref="T:System.Net.HttpWebResponse"/>实例中返回的字符串。
        /// </summary>
        /// <param name="response"><see cref="T:System.Net.HttpWebResponse"/>实例对象。</param>
        /// <param name="encoding">编码类型。</param>
        /// <returns>返回页面的字符串。</returns>
        public static string GetPageText(HttpWebResponse response, Encoding encoding)
        {
            using (Stream stream = response.GetResponseStream())
            {
                string name = response.ContentEncoding.Trim();
                if (encoding == null)
                {
                    try
                    {
                        encoding = Encoding.GetEncoding(name);
                    }
                    catch
                    {
                        encoding = Encoding.UTF8;
                    }
                }
                StreamReader reader = null;
                try
                {
                    if (string.Compare(name, "gzip", true) == 0)
                    {
                        reader = new StreamReader(new GZipStream(stream, CompressionMode.Decompress), encoding);
                    }
                    else if (string.Compare(name, "deflate", true) == 0)
                    {
                        reader = new StreamReader(new DeflateStream(stream, CompressionMode.Decompress), encoding);
                    }
                }
                catch { }
                if (reader == null)
                {
                    reader = new StreamReader(stream, encoding);
                }
                string result = reader.ReadToEnd();
                reader.Close();
                return result;
            }
        }
        /// <summary>
        /// 获取页面的字符串。
        /// </summary>
        /// <param name="url">URL字符串。</param>
        /// <param name="encoding">编码类型。</param>
        /// <returns>返回页面的字符串。</returns>
        public static string GetPageText(string url, Encoding encoding)
        {
            return GetPageText(url, referer, encoding);
        }
        /// <summary>
        /// 获取页面的字符串。
        /// </summary>
        /// <param name="url">URL字符串。</param>
        /// <returns>返回页面的字符串。</returns>
        public static string GetPageText(string url)
        {
            return GetPageText(url, referer);
        }
        /// <summary>
        /// 获取页面的字符串。
        /// </summary>
        /// <param name="url">URL字符串。</param>
        /// <param name="encoding">编码类型。</param>
        /// <returns>返回页面的字符串。</returns>
        public static string GetPageText(string url, string referral, Encoding encoding = null)
        {
            return GetPageText(GetResponse(url, referral), encoding);
        }
        /// <summary>
        /// 获取<see cref="T:System.Net.HttpWebResponse"/>实例对象。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebResponse"/>实例对象。</returns>
        public static HttpWebResponse GetResponse(string url)
        {
            return GetResponse(url, referer);
        }
        /// <summary>
        /// 获取当前URL地址的字符串。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用地址。</param>
        /// <returns>返回当前URL地址的字符串。</returns>
        public static HttpWebResponse GetResponse(string url, string referral)
        {
            return (HttpWebResponse)CreateRequest(url, referral).GetResponse();
        }
        /// <summary>
        /// 获取<see cref="T:System.Net.HttpWebResponse"/>实例对象。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebResponse"/>实例对象。</returns>
        public static string GetSafePageText(string url, string referral)
        {
            return GetSafePageText(url, referer, null);
        }
        /// <summary>
        /// 获取当前URL地址的字符串。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用地址。</param>
        /// <param name="encoding">编码实例对象。</param>
        /// <returns>返回当前URL地址的字符串。</returns>
        public static string GetSafePageText(string url, string referral, Encoding encoding)
        {
            HttpWebResponse safeResponse = GetSafeResponse(url, referral);
            if (safeResponse != null)
            {
                if (IsContentTypeValid(safeResponse.ContentType) && (safeResponse.ContentLength < 18750L))
                {
                    return GetPageText(safeResponse, encoding);
                }
                safeResponse.Close();
            }
            return null;
        }
        /// <summary>
        /// 获取<see cref="T:System.Net.HttpWebResponse"/>实例对象。
        /// </summary>
        /// <param name="url">URL地址。</param>
        /// <param name="referral">引用地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebResponse"/>实例对象。</returns>
        public static HttpWebResponse GetSafeResponse(string url, string referral)
        {
            return (HttpWebResponse)CreateSafeRequest(url, referral).GetResponse();
        }
        /// <summary>
        /// 得到的文本是否符合ContentType类型。
        /// </summary>
        /// <param name="contentType">ContentType类型。</param>
        /// <returns>返回是否符合该类型。</returns>
        public static bool IsContentTypeValid(string contentType)
        {
            if (string.IsNullOrEmpty(contentType))
                return false;
            int index = contentType.IndexOf(';');
            contentType = index == -1 ? contentType : contentType.Substring(0, index);
            contentType = contentType.Trim().ToLower();
            return contentType == "text/html" || contentType == "text/xhtml" || contentType == "application/xhtml+xml" || contentType == "text/plain" || contentType == "text/sgml" || contentType == "text/xml";
        }
        /// <summary>
        /// 发送数据到服务器。
        /// </summary>
        /// <param name="wreq"><see cref="T:System.Net.HttpWebRequest"/>实例对象。</param>
        /// <param name="items">发送的项。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebResponse"/>实例对象。</returns>
        public static HttpWebResponse MakeHttpPost(HttpWebRequest wreq, NameValueCollection items)
        {
            if (wreq == null)
            {
                throw new Exception("HttpWebRequest is not initialized");
            }
            if (items == null || items.Count == 0)
            {
                throw new Exception("No post items");
            }
            byte[] bytes = Encoding.UTF8.GetBytes(items.Join("&"));
            wreq.Method = "POST";
            wreq.ContentLength = bytes.Length;
            wreq.ContentType = "application/x-www-form-urlencoded";
            wreq.KeepAlive = false;
            using (Stream stream = wreq.GetRequestStream())
            {
                stream.Write(bytes, 0, bytes.Length);
                stream.Close();
                return (wreq.GetResponse() as HttpWebResponse);
            }
        }
        /// <summary>
        /// 发送数据到服务器。
        /// </summary>
        /// <param name="url">发送的URL地址。</param>
        /// <param name="items">发送的项。</param>
        /// <param name="referral">引用网址地址。</param>
        /// <returns>返回<see cref="T:System.Net.HttpWebResponse"/>实例对象。</returns>
        public static HttpWebResponse MakeHttpPost(string url, NameValueCollection items, string referral = null)
        {
            return MakeHttpPost(CreateRequest(url, referral), items);
        }
        /// <summary>
        /// 获取是否使用网页代理。
        /// </summary>
        public static bool HasWebProxy
        {
            get
            {
                return (WebProxy != null);
            }
        }
        /// <summary>
        /// 获取用户代理字符串。
        /// </summary>
        public static string UserAgent
        {
            get
            {
                return userAgent;
            }
        }
        /// <summary>
        /// 获取或设置网页代理对象。
        /// </summary>
        public static WebProxy WebProxy { get; set; }
    }
}
